package com.contest.service;

import com.contest.dto.request.CreateUserRequest;
import com.contest.dto.request.UpdateUserRequest;
import com.contest.dto.response.PagedResponse;
import com.contest.dto.response.UserDto;
import com.contest.entity.User;
import com.contest.entity.UserRole;
import com.contest.exception.UserAlreadyExistsException;
import com.contest.exception.UserNotFoundException;
import com.contest.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@Transactional
public class UserService {
    
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    /**
     * 获取所有用户（分页）
     */
    public PagedResponse<UserDto> getAllUsers(int page, int size, String sortBy, String sortDir, 
                                            String keyword, UserRole role, Boolean enabled) {
        logger.info("获取用户列表 - 页码: {}, 大小: {}, 排序: {} {}, 关键词: {}, 角色: {}, 启用状态: {}", 
                   page, size, sortBy, sortDir, keyword, role, enabled);
        
        Sort sort = sortDir.equalsIgnoreCase("desc") ? 
                   Sort.by(sortBy).descending() : Sort.by(sortBy).ascending();
        Pageable pageable = PageRequest.of(page, size, sort);
        
        Page<User> userPage = userRepository.findUsersWithFilters(keyword, role, enabled, pageable);
        
        List<UserDto> userDtos = userPage.getContent().stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
        
        return new PagedResponse<>(
                userDtos,
                userPage.getNumber(),
                userPage.getSize(),
                userPage.getTotalElements(),
                userPage.getTotalPages(),
                userPage.isFirst(),
                userPage.isLast()
        );
    }
    
    /**
     * 根据ID获取用户
     */
    public UserDto getUserById(Long userId) {
        logger.info("根据ID获取用户: {}", userId);
        
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new UserNotFoundException("用户不存在，ID: " + userId));
        
        return convertToDto(user);
    }
    
    /**
     * 创建新用户
     */
    public UserDto createUser(CreateUserRequest request) {
        logger.info("创建新用户: {}", request.getUsername());
        
        // 检查用户名是否已存在
        if (userRepository.existsByUsername(request.getUsername())) {
            throw new UserAlreadyExistsException("用户名已存在: " + request.getUsername());
        }
        
        // 检查邮箱是否已存在
        if (userRepository.existsByEmail(request.getEmail())) {
            throw new UserAlreadyExistsException("邮箱已存在: " + request.getEmail());
        }
        
        // 创建新用户
        User user = new User();
        user.setUsername(request.getUsername());
        user.setEmail(request.getEmail());
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        user.setRole(request.getRole());
        user.setEnabled(request.isEnabled());
        
        User savedUser = userRepository.save(user);
        logger.info("用户创建成功: {}", savedUser.getUsername());
        
        return convertToDto(savedUser);
    }
    
    /**
     * 更新用户信息
     */
    public UserDto updateUser(Long userId, UpdateUserRequest request) {
        logger.info("更新用户信息: {}", userId);
        
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new UserNotFoundException("用户不存在，ID: " + userId));
        
        // 更新用户名（如果提供且不同）
        if (request.getUsername() != null && !request.getUsername().equals(user.getUsername())) {
            if (userRepository.existsByUsername(request.getUsername())) {
                throw new UserAlreadyExistsException("用户名已存在: " + request.getUsername());
            }
            user.setUsername(request.getUsername());
        }
        
        // 更新邮箱（如果提供且不同）
        if (request.getEmail() != null && !request.getEmail().equals(user.getEmail())) {
            if (userRepository.existsByEmail(request.getEmail())) {
                throw new UserAlreadyExistsException("邮箱已存在: " + request.getEmail());
            }
            user.setEmail(request.getEmail());
        }
        
        // 更新密码（如果提供）
        if (request.getPassword() != null && !request.getPassword().trim().isEmpty()) {
            user.setPassword(passwordEncoder.encode(request.getPassword()));
        }
        
        // 更新角色（如果提供）
        if (request.getRole() != null) {
            user.setRole(request.getRole());
        }
        
        // 更新启用状态（如果提供）
        if (request.getEnabled() != null) {
            user.setEnabled(request.getEnabled());
        }
        
        User updatedUser = userRepository.save(user);
        logger.info("用户更新成功: {}", updatedUser.getUsername());
        
        return convertToDto(updatedUser);
    }
    
    /**
     * 删除用户
     */
    public void deleteUser(Long userId) {
        logger.info("删除用户: {}", userId);
        
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new UserNotFoundException("用户不存在，ID: " + userId));
        
        userRepository.delete(user);
        logger.info("用户删除成功: {}", user.getUsername());
    }
    
    /**
     * 启用用户
     */
    public UserDto enableUser(Long userId) {
        logger.info("启用用户: {}", userId);
        
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new UserNotFoundException("用户不存在，ID: " + userId));
        
        user.setEnabled(true);
        User updatedUser = userRepository.save(user);
        
        logger.info("用户启用成功: {}", updatedUser.getUsername());
        return convertToDto(updatedUser);
    }
    
    /**
     * 禁用用户
     */
    public UserDto disableUser(Long userId) {
        logger.info("禁用用户: {}", userId);
        
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new UserNotFoundException("用户不存在，ID: " + userId));
        
        user.setEnabled(false);
        User updatedUser = userRepository.save(user);
        
        logger.info("用户禁用成功: {}", updatedUser.getUsername());
        return convertToDto(updatedUser);
    }
    
    /**
     * 获取用户统计信息
     */
    public UserStatsDto getUserStats() {
        logger.info("获取用户统计信息");
        
        long totalUsers = userRepository.count();
        long adminCount = userRepository.countByRole(UserRole.ADMIN);
        long teacherCount = userRepository.countByRole(UserRole.TEACHER);
        long studentCount = userRepository.countByRole(UserRole.STUDENT);
        long enabledUsers = userRepository.findByEnabledTrue().size();
        long disabledUsers = userRepository.findByEnabledFalse().size();
        
        return new UserStatsDto(totalUsers, adminCount, teacherCount, studentCount, enabledUsers, disabledUsers);
    }
    
    /**
     * 将User实体转换为UserDto
     */
    private UserDto convertToDto(User user) {
        return new UserDto(
                user.getId(),
                user.getUsername(),
                user.getEmail(),
                user.getRole(),
                user.isEnabled(),
                user.getCreatedAt(),
                user.getUpdatedAt()
        );
    }
    
    /**
     * 用户统计信息DTO
     */
    public static class UserStatsDto {
        private long totalUsers;
        private long adminCount;
        private long teacherCount;
        private long studentCount;
        private long enabledUsers;
        private long disabledUsers;
        
        public UserStatsDto(long totalUsers, long adminCount, long teacherCount, 
                           long studentCount, long enabledUsers, long disabledUsers) {
            this.totalUsers = totalUsers;
            this.adminCount = adminCount;
            this.teacherCount = teacherCount;
            this.studentCount = studentCount;
            this.enabledUsers = enabledUsers;
            this.disabledUsers = disabledUsers;
        }
        
        // Getters
        public long getTotalUsers() { return totalUsers; }
        public long getAdminCount() { return adminCount; }
        public long getTeacherCount() { return teacherCount; }
        public long getStudentCount() { return studentCount; }
        public long getEnabledUsers() { return enabledUsers; }
        public long getDisabledUsers() { return disabledUsers; }
    }
}